home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 4 / FM Towns Free Software Collection 4 - Disc 1.iso / t_os / wstype / source / tree.c < prev    next >
C/C++ Source or Header  |  1991-10-18  |  7KB  |  367 lines

  1. /***   [tree.c]
  2. *
  3. *    ディレクトリツリー情報 関連        (C)ささがわ
  4. *
  5. *    For GNU C Compiler (GCC)   Version 1.39
  6. *
  7. ***/
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <direct.h>
  13. #include <dos.h>
  14. #include "tree.h"
  15. #include "others.h"
  16.  
  17. #define DEFAULT_BUF 150        /* 初期のバッファサイズ */
  18. #define ADD_BUF     50        /* 追加バッファサイズ */
  19. #define DRBUFDEF    50        /* 初期のバッファサイズ */
  20. #define DRBUFADD    30        /* 追加バッファサイズ */
  21.  
  22. static struct tree_t    *trbuf;
  23. static int  cap, nest, mnest;
  24. static int    bufoff, bufsz;
  25. static int    DRbuf_sz, DRbuf_err;
  26. static unsigned short    DRbuf_tab[40], DRbuf_num[40];
  27. static char (*DRbuf)[13];
  28.  
  29. static int    (*TR_break)(void);
  30. static int    Set_tree(void);
  31. static int    Buf_extend(void);
  32. static int    Set_tree_sub(void);
  33. static int    Get_subdir(int, char *);
  34. static int    Get_subdir_sub(int, char *);
  35. static int  DRbuf_extend(void);
  36.  
  37. /***
  38. *    ディレクトリツリー格納関数
  39. *        入力:    dt:ツリー情報構造体へのポインタ   bt:中断用関数へのポインタ
  40. *        戻り値:    0 正常終了   -1 メモリーエラー   -2 ディスクエラー   -3 中断
  41. ***/
  42. int Get_dirtree(struct dirtree_t *dt, int c, int (*br)(void)) {
  43.     int        ret;
  44.     
  45.     cap = c;
  46.     TR_break = br;
  47.     if ((DRbuf = malloc(13 * DRBUFDEF)) == NULL) {
  48.         DRbuf_sz = 0;
  49.         DRbuf_err = 1;
  50.     } else {
  51.         DRbuf_sz = DRBUFDEF;
  52.         DRbuf_tab[0] = 0;
  53.         DRbuf_err = 0;
  54.     }
  55.     
  56.     bufsz = DEFAULT_BUF;
  57.     while ((ret = Set_tree()) == -4);
  58.     
  59.     if (ret != 0) {
  60.         dt->tr = NULL;
  61.         dt->numd = -1;
  62.         dt->numc = -1;
  63.     } else {
  64.         int        i;
  65.         unsigned char    branch[40];
  66.         
  67.         dt->tr = trbuf;
  68.         dt->numd = bufoff;
  69.         dt->numc = mnest + 1;
  70.         for (i = 0; i < 40; i++)
  71.             branch[i] = 0;
  72.         for (i = 0; i < dt->numd; i++) {
  73.             branch[trbuf[i].nest - 1] = 1;
  74.             TR_branch(0, branch, trbuf[i].branch);
  75.             if (trbuf[i].dirn == 0xffff)
  76.                 branch[trbuf[i].nest - 1] = 0;
  77.         }
  78.     }
  79.     
  80.     free(DRbuf);
  81.     return ret;
  82. }
  83.  
  84. /* バッファ格納関数 */
  85. static int Set_tree(void) {
  86.     int        ret;
  87.     char    dir[70];
  88.     
  89.     TR_bufrel();
  90.     bufoff = 0;
  91.     if ((trbuf = (struct tree_t *)malloc(bufsz * sizeof(struct tree_t))) == NULL)
  92.         return -1;
  93.     
  94.     dir[0] = '\\';
  95.     if (Get_curdir(0, dir + 1) || chdir("\\"))
  96.         return -2;
  97.     
  98.     nest = 0;
  99.     mnest = 0;
  100.     trbuf[bufoff].nest = (unsigned char)nest++;
  101.     trbuf[bufoff].dirn = 0xffff;
  102.     strcpy(trbuf[bufoff++].name, "\\");
  103.     ret = Set_tree_sub();
  104.     if (ret != -2 && chdir(dir))
  105.         return -2;
  106.     
  107.     return ret;
  108. }
  109.  
  110. static int Buf_extend(void) {
  111.     int        p;
  112.     void    *buf2;
  113.     
  114.     p = bufsz;
  115.     bufsz += ADD_BUF;
  116.     if ((buf2 = malloc(bufsz * sizeof(struct tree_t))) == NULL)
  117.         return -1;
  118.     memcpy(buf2, trbuf, p * sizeof(struct tree_t));
  119.     free(trbuf);
  120.     trbuf = buf2;
  121.     
  122.     return 0;
  123. }
  124.  
  125. /* ディレクトリ再帰関数 */
  126. /* 戻り値:0 正常終了   -4 リトライ   -2 ディスクエラー   -3 中断 */
  127. static int Set_tree_sub(void) {
  128.     int        ret, dirn = 0, p = -1;
  129.     char    buf[15];
  130.     
  131.     if (TR_break())
  132.         return -3;
  133.     while (Get_subdir(dirn, buf)) {
  134.         p = bufoff++;
  135.         trbuf[p].nest = (unsigned char)nest;
  136.         trbuf[p].dirn = dirn++;
  137.         if (!cap)
  138.             strlow(0, (unsigned char *)buf);
  139.         strcpy(trbuf[p].name, buf);
  140.         if (bufoff >= bufsz) {
  141.             if (Buf_extend())
  142.                 return -4;
  143.         }
  144.         
  145.         if (chdir(buf))
  146.             return -2;
  147.         nest++;
  148.         if (ret = Set_tree_sub())
  149.             return ret;
  150.     }
  151.     if (TR_break())
  152.         return -3;
  153.     
  154.     if (p >= 0) {
  155.         trbuf[p].dirn = 0xffff;
  156.         if (nest > mnest)
  157.             mnest = nest;
  158.     }
  159.     
  160.     if (nest > 1) {
  161.         if (chdir(".."))
  162.             return -2;
  163.         nest--;
  164.     }
  165.     
  166.     return 0;
  167. }
  168.  
  169. /* カレントディレクトリ中のnd番目のサブディレクトリを検索する関数 */
  170. /* 見つかった場合はbufに格納し, 戻り値に1を返す    */
  171. static int Get_subdir(int nd, char *buf) {
  172.     int     ret;
  173.     
  174.     if (nd == 0) {
  175.         int        p, err = 0;
  176.         struct find_t    ft;
  177.         
  178.         p = DRbuf_tab[nest - 1];
  179.         if (!_dos_findfirst("*.*", _A_SUBDIR, &ft)) {
  180.             if (ft.name[0] != '.' && ft.attrib & _A_SUBDIR) {
  181.                 if (p >= DRbuf_sz)
  182.                     err = DRbuf_extend();
  183.                 if (!err)
  184.                     strcpy((char *)(DRbuf + p++), ft.name);
  185.             }
  186.             while (!err && !_dos_findnext(&ft)) {
  187.                 if (ft.name[0] != '.' && ft.attrib & _A_SUBDIR) {
  188.                     if (p >= DRbuf_sz)
  189.                         err = DRbuf_extend();
  190.                     if (!err)
  191.                         strcpy((char *)(DRbuf + p++), ft.name);
  192.                 }
  193.             }
  194.         }
  195.         
  196.         if (err) {
  197.             DRbuf_tab[nest] = DRbuf_tab[nest - 1];
  198.             DRbuf_num[nest - 1] = 0xffff;
  199.             if (Get_subdir_sub(0, buf))
  200.                 ret = 1;
  201.             else
  202.                 ret = 0;
  203.         } else {
  204.             DRbuf_tab[nest] = p;
  205.             if ((DRbuf_num[nest - 1] = DRbuf_tab[nest] - DRbuf_tab[nest - 1]) != 0) {
  206.                 strcpy(buf, DRbuf[DRbuf_tab[nest - 1]]);
  207.                 ret = 1;
  208.             } else {
  209.                 ret = 0;
  210.             }
  211.         }
  212.     } else {
  213.         if (DRbuf_num[nest - 1] == 0xffff) {
  214.             if (Get_subdir_sub(nd, buf))
  215.                 ret = 1;
  216.             else
  217.                 ret = 0;
  218.         } else if (nd > DRbuf_num[nest - 1] - 1) {
  219.             ret = 0;
  220.         } else {
  221.             strcpy(buf, DRbuf[DRbuf_tab[nest - 1] + nd]);
  222.             ret = 1;
  223.         }
  224.     }
  225.     
  226.     return ret;
  227. }
  228.  
  229. static int Get_subdir_sub(int nd, char *buf) {
  230.     int        nd2 = 0;
  231.     struct find_t    ft;
  232.     
  233.     if (!_dos_findfirst("*.*", _A_SUBDIR, &ft)) {
  234.         if (ft.name[0] != '.' && ft.attrib & _A_SUBDIR) {
  235.             if (nd2 == nd) {
  236.                 strcpy(buf, ft.name);
  237.                 return 1;
  238.             }
  239.             nd2++;
  240.         }
  241.         while (!_dos_findnext(&ft)) {
  242.             if (ft.name[0] != '.' && ft.attrib & _A_SUBDIR) {
  243.                 if (nd2 == nd) {
  244.                     strcpy(buf, ft.name);
  245.                     return 1;
  246.                 }
  247.                 nd2++;
  248.             }
  249.         }
  250.     }
  251.     
  252.     return 0;
  253. }
  254.  
  255. static int DRbuf_extend(void) {
  256.     void    *tmp;
  257.     
  258.     if (DRbuf_err || (tmp = malloc((DRbuf_sz + DRBUFADD) * 13)) == NULL) {
  259.         DRbuf_err = 1;
  260.         return -1;
  261.     }
  262.     memcpy(tmp, DRbuf, DRbuf_sz * 13);
  263.     free(DRbuf);
  264.     DRbuf = tmp;
  265.     DRbuf_sz += DRBUFADD;
  266.     
  267.     return 0;
  268. }
  269.  
  270. /* ツリー情報用バッファを開放する関数 */
  271. void TR_bufrel(void) {
  272.     free(trbuf);
  273.     trbuf = NULL;
  274. }
  275.  
  276. void TR_branch(int mode, unsigned char *byt, unsigned char *bit) {
  277.     int        i;
  278.     
  279.     if (mode) {
  280.         for (i = 0; i < 40; i++) {
  281.             if (bit[i / 8] >> i % 8 & 1)
  282.                 byt[i] = 1;
  283.             else
  284.                 byt[i] = 0;
  285.         }
  286.     } else {
  287.         for (i = 0; i < 5; i++)
  288.             bit[i] = 0;
  289.         for (i = 0; i < 40; i++) {
  290.             if (byt[i])
  291.                 bit[i / 8] += (unsigned char)(1 << i % 8);
  292.         }
  293.     }
  294. }
  295. int TR_Search_curd(int mode, int *curd, char *dir, struct dirtree_t *dt) {
  296.     int        ret;
  297.     
  298.     if (mode) {
  299.         int        n = -1, nest = 0, flag, len;
  300.         char    *ptr;
  301.         
  302.         ptr = strchr(dir, '\\');
  303.         len = 1;
  304.         do {
  305.             int        i;
  306.             
  307.             flag = 0;
  308.             do {
  309.                 while (dt->tr[++n].nest != (unsigned char)nest);
  310.                 if (strncmp(ptr, dt->tr[n].name, len) == 0) {
  311.                     flag = 1;
  312.                     break;
  313.                 }
  314.             } while (dt->tr[n].dirn != 0xffff);
  315.             if (!flag)
  316.                 break;
  317.             
  318.             i = (int)strchr(ptr, '\\');
  319.             (i == 0) ? (ptr = strchr(ptr, '\0')) : (ptr = (char *)i + 1);
  320.             i = (int)strchr(ptr, '\\');
  321.             (i == 0) ? (len = strlen(ptr)) : (len = (char *)i - ptr);
  322.             nest++;
  323.         } while (*ptr != '\0');
  324.         if (flag) {
  325.             ret = 1;
  326.             *curd = n;
  327.         } else {
  328.             ret = 0;
  329.             *curd = -1;
  330.         }
  331.     } else {
  332.         int        i, nst;
  333.         char    *p, buf[70], buf2[70];
  334.         
  335.         strcpy(buf, dt->tr[*curd].name);
  336.         if (dt->tr[*curd].nest != 0)
  337.             strcat(buf, "\\");
  338.         nst = dt->tr[*curd].nest;
  339.         for (i = *curd - 1; i > 0; i--) {
  340.             if (nst <= dt->tr[i].nest)
  341.                 continue;
  342.             
  343.             strcat(strcat(buf, dt->tr[i].name), "\\");
  344.             nst--;
  345.         }
  346.         
  347.         strcpy(buf2, "\\");
  348.         p = strchr(buf, '\0');
  349.         for (i = 0; i < dt->tr[*curd].nest; i++) {
  350.             int        l;
  351.             
  352.             l = (int)p;
  353.             while (--p > buf && p[-1] != '\\');
  354.             l -= (int)p;
  355.             
  356.             strncat(buf2, p, l);
  357.         }
  358.         if (dt->tr[*curd].nest != 0)
  359.             strchr(buf2, '\0')[-1] = '\0';
  360.         strcpy(dir, buf2);
  361.         
  362.         ret = 1;
  363.     }
  364.     
  365.     return ret;
  366. }
  367.